/**
 * @class dfly.Container
 * @inherits WireIt.Container
 * @constructor
 * @param {Obj} config configuration object (see WireIt.Container)
 */
dfly.Container = function(config,layer) {
   
   // Load the module
   this.module = dfly.ModuleModel.get(config.moduleName);
   
   // Create the dflyModule
   this.dflyModule = new dfly.Module(this.module);
   
   var that = this;
   this.dflyModule.setOutput = function(outputName, value) { that.setOutput(outputName, value); };   
   
   dfly.Container.superclass.constructor.call(this, config, layer);
   
   // Set the title
   var path = config.moduleName.split('/');
   this.ddHandle.innerHTML = path[path.length-1];
   
   // Construit les terminaux
   this.buildTerminals();
   
   
   // Reposition the terminals when the jsBox is being resized
   this.ddResize.eventResize.subscribe(function(e, args) {
      this.redrawAllWires();
   }, this, true);
   
};
YAHOO.extend(dfly.Container, WireIt.Container, {
   
   /**
    * Execution functions
    */
   setOutput: function(outputName, value) {
      
      console.log("container setOutput", outputName, value);
      
      // Removing the spinner in some time
      var that = this;
      setTimeout(function() { YAHOO.util.Dom.removeClass(that.ddHandle, "running"); }, 800);
      
      if(!this.resultOutputValues) {
         this.resultOutputValues = {};
      }
      this.resultOutputValues[outputName] = value;
      
      // Run the connected modules:
      for(var i = 0 ; i < this.wires.length ; i++) {
         var w = this.wires[i];
         var myTerm = (w.terminal1.container == this) ? w.terminal1 : w.terminal2;
         if(myTerm.dflyName.substr(0,6) == "output") {
            var otherTerm = w.getOtherTerminal(myTerm);
            var otherContainer = otherTerm.container;
            if(typeof otherContainer.run == "function") {
               otherContainer.run();
            }
         }
      }
   },
   
   getOutputValue: function(outputName) {
      if(this.config.moduleName == '/system/input') {
         var val = this.form.getValue();
         return val.type.defaultValue;
      }
      else {
         if(this.resultOutputValues) {
            if(this.resultOutputValues.hasOwnProperty(outputName)) {
               return this.resultOutputValues[outputName];
            }
         }
      }
      return null;
   },
   
   getRunParams: function() {
      
      var params = this.form.getValue();
      
      for(var i = 0 ; i < this.wires.length ; i++) {
         var w = this.wires[i];
         var myTerm = (w.terminal1.container == this) ? w.terminal1 : w.terminal2;
         
         if(myTerm.dflyName.substr(0,5) == "input") {
            var otherTerm = w.getOtherTerminal(myTerm);
            var otherContainer = otherTerm.container;
            var linkedValue = otherContainer.getOutputValue(otherTerm.dflyName);
         
            if(linkedValue === null) {
               return false;
            }
         
            // Get the input name by removing "input_" prefix
            var inputName = myTerm.dflyName.substr(6);
         
            var isArrayParam = inputName.match(/(.*)\[([0-9]*)\]$/);
            if(isArrayParam) {
               var arrayName = isArrayParam[1];
               var index = parseInt(isArrayParam[2]);
               params[arrayName][index] = linkedValue;
            }
            else {
               params[inputName] = linkedValue;
            }
   
         }
      }
      
      // Get the connected terminals/containers values
      // and mix them with this.form.getValue
      return params;
   },
   
   run: function() {
      
      if(dfly.layer.blockExecution) { return; }
      
      var params = this.getRunParams();
      if(params !== false) {
         
         YAHOO.util.Dom.addClass(this.ddHandle, "running");
         
         this.dflyModule.run(params);
      }
   },
   
   formUpdated: function() {
      this.redrawAllWires();
      this.run();
   },
   
   onAddWire: function(event, args) {
      dfly.Container.superclass.onAddWire.call(this, event, args);
      
      // We run only if this is an "input" wire:
      var wire = args[0];
      var term = (wire.terminal1.container == this) ? wire.terminal1 : wire.terminal2;
      if(term.dflyName && term.dflyName.substr(0,6) == "input_") {
         this.run();
      }
      
   },
   
   /*onRemoveWire: function(event, args) {
      dfly.Container.superclass.onRemoveWire.call(this, event, args);
      this.run();
   },*/
    
   /**
    * Build the form using inputEx and appendIt to the body
    */
   buildParamsForm: function(paramsInputs) {
      
      // Extend the params with default values :
      for(var i = 0 ; i < paramsInputs.length ; i++) {
         if(typeof paramsInputs[i].inputParams == "undefined") { paramsInputs[i].inputParams = {}; }
         if(typeof paramsInputs[i].inputParams.wirable == "undefined") { paramsInputs[i].inputParams.wirable = "true";}
         paramsInputs[i].inputParams.container =  this;
      }
      
      this.form = new inputEx.Group(paramsInputs);
      this.form.updatedEvt.subscribe(this.formUpdated, this, true);
      
      if(this.config.formValue) {
         this.form.setValue(this.config.formValue);
      }
      
      this.bodyEl.appendChild( this.form.getEl() );
   },
   
   
   /**
    * Build the output terminals (in a one-row table to position them)
    */
   buildOutputs: function(paramsOutputs) {
      
      var table = WireIt.cn('table', null, {position: "absolute", bottom: "-10px", width: "100%"});
      var tbody = WireIt.cn('tbody');
      var tr=WireIt.cn('tr');
      table.appendChild(tbody);
      tbody.appendChild(tr);
      var w=(100/paramsOutputs.length)+"%";
      for(var i = 0 ; i < paramsOutputs.length ; i++) {
         var output = paramsOutputs[i]; // {name, type}
         var td = WireIt.cn('td', null, {width: w});
         var term = new WireIt.Terminal(td, {
            direction: [0,1],
            fakeDirection: [-1, 0],
            ddConfig: {
               type: "output",
               allowedTypes: ["input"]
            } }, this);
            
         // Dfly name for this terminal
         term.dflyName = "output_"+output.name;
            
         tr.appendChild(td);
         WireIt.sn(term.el, null, {position: "inherit", margin: "auto"});
         
         this.terminals.push(term);
         term.eventAddWire.subscribe(this.onAddWire, this, true);
         term.eventRemoveWire.subscribe(this.onRemoveWire, this, true);
         
         // Get the mouseover and mouseout event to display the tooltip
         YAHOO.util.Event.addListener(term.el, 'mouseover', function(e) {
            dfly.tooltip.mouseOverTerminal(this);
         }, term, true);
         
         YAHOO.util.Event.addListener(term.el, 'mouseout', function(e) {
            dfly.tooltip.mouseOutTerminal(this);
         }, term, true);
         
      }
      
      this.el.appendChild(table);
   },
   
    
   /**
    * Build the terminals based on module.terminals
    */
   buildTerminals: function() {
      
      // Remove all previous terminals
      if(this.terminals) {
         for(var i = 0; i < this.terminals.length ; i++)
            this.terminals[i].remove();
      }

      var params = this.module.parameters;

      // Build the form
      if(params && params.inputs) {
         this.buildParamsForm(params.inputs);
      }

      // Build the outputs
      if(params && params.outputs) {
         this.buildOutputs(params.outputs);
      }
      
   },
   
   getConfig: function() {
      
      var obj = dfly.Container.superclass.getConfig.call(this);
      
      obj.moduleName = this.config.moduleName;
      
      obj.formValue = this.form.getValue();
      
      return obj;
   },
   
   findTerminalByName: function(name) {
      for(var i = 0 ; i < this.terminals.length ; i++) {
         if(this.terminals[i].dflyName == name) {
            return this.terminals[i];
         }
      }
      return null;
   }
   
   
});
